import { BadRequestException, Injectable } from '@nestjs/common';
import { Like, Repository, Between, LessThanOrEqual, MoreThanOrEqual } from 'typeorm';
import { PointsGoodsEntity } from './points-goods.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { CreatePointsGoodsDto, FindPointsGoodsListDto, UpdatePointsGoodsDto } from './points-goods.dto';
import { TenantEntity } from '~/modules/tenant/tenant.entity';
import { UploadService } from '~/modules/tools/upload/upload.service';
import { CommonStatus } from '~/common/entity/common.entity';
import { Pagination } from '~/helper/paginate/pagination';
import { paginate } from '~/helper/paginate';
import { standardPaginate, StandardPagination } from '~/helper/paginate';
import { PointsGoodsExchangeService } from './points-goods-exchange/points-goods-exchange.service';

@Injectable()
export class PointsGoodsService {
  constructor(
    @InjectRepository(PointsGoodsEntity)
    private readonly pointsGoodsRepository: Repository<PointsGoodsEntity>,
    private readonly uploadService: UploadService,
    private readonly pointsGoodsExchangeService: PointsGoodsExchangeService
  ) {}

  async getGoods(id: number): Promise<PointsGoodsEntity> {
    return await this.pointsGoodsRepository.findOneBy({
      id,
    });
  }

  async create(dto: CreatePointsGoodsDto, tenantId: number): Promise<PointsGoodsEntity> {
    const pointsGoods = this.pointsGoodsRepository.create();

    pointsGoods.name = dto.name;
    pointsGoods.description = dto.description;
    pointsGoods.price = dto.price;
    pointsGoods.tenant = { id: tenantId } as TenantEntity;
    pointsGoods.image = dto?.image ?? '';

    return await this.pointsGoodsRepository.save(pointsGoods);
  }

  async update(id: number, dto: UpdatePointsGoodsDto, tenantId: number): Promise<PointsGoodsEntity> {
    const existingGoods = await this.pointsGoodsRepository.findOne({
      where: { id, tenant: { id: tenantId } }
    });

    if (!existingGoods) {
      throw new BadRequestException('商品不存在或无权限访问');
    }

    // 只更新提供的字段
    if (dto.name !== undefined) {
      existingGoods.name = dto.name;
    }
    if (dto.description !== undefined) {
      existingGoods.description = dto.description;
    }
    if (dto.price !== undefined) {
      existingGoods.price = dto.price;
    }
    if (dto.image !== undefined) {
      existingGoods.image = dto.image;
    }

    return await this.pointsGoodsRepository.save(existingGoods);
  }

  async findRecommend(tenantId: number): Promise<PointsGoodsEntity[]> {
    return await this.findAll(tenantId, 2);
  }

  async findAll(tenantId: number, take?: number): Promise<PointsGoodsEntity[]> {
    return await this.pointsGoodsRepository.find({
      where: {
        status: CommonStatus.YES,
        tenant: { id: tenantId },
      },
      // 根据创建时间降序排列
      order: {
        exchangeCount: 'DESC',
      },
      // 限制2条, take 有值再限制，无则不限制
      take: take ?? null,
    });
  }

  async findByList({
    page,
    pageSize,
    name,
    field,
    order,
    tenantId,
  }: FindPointsGoodsListDto & { tenantId: number }): Promise<Pagination<PointsGoodsEntity>> {
    const queryBuilder = await this.pointsGoodsRepository
      .createQueryBuilder('ah_points_goods')
      .where({
        ...(name ? { name: Like(`%${name}%`) } : null),
        tenant: { id: tenantId },
      });

    if (field && order) {
      queryBuilder.orderBy(
        `ah_points_goods.${field}`,
        order.toUpperCase() === 'ASC' ? 'ASC' : 'DESC'
      );
    }

    return paginate<PointsGoodsEntity>(queryBuilder, {
      page,
      pageSize,
    });
  }

  /**
   * 分页查询积分商品列表（标准分页实现）
   * @param dto 分页查询参数
   * @param tenantId 租户ID
   * @returns 标准分页结果
   */
  async findPage(dto: FindPointsGoodsListDto, tenantId: number): Promise<StandardPagination<PointsGoodsEntity>> {
    const queryBuilder = this.pointsGoodsRepository
      .createQueryBuilder('goods')
      .select([
        'goods.id',
        'goods.name',
        'goods.description',
        'goods.price',
        'goods.image',
        'goods.exchangeCount',
        'goods.status',
        'goods.createdAt',
        'goods.updatedAt',
      ])
      .where('goods.status = :status', { status: CommonStatus.YES })
      .andWhere('goods.tenant.id = :tenantId', { tenantId })
      .orderBy('goods.createdAt', 'DESC');

    // 根据商品名称模糊查询
    if (dto.name) {
      queryBuilder.andWhere('goods.name LIKE :name', { name: `%${dto.name}%` });
    }

    // 根据价格范围筛选
    if (dto.minPrice !== undefined && dto.maxPrice !== undefined) {
      queryBuilder.andWhere('goods.price BETWEEN :minPrice AND :maxPrice', {
        minPrice: dto.minPrice,
        maxPrice: dto.maxPrice,
      });
    } else if (dto.minPrice !== undefined) {
      queryBuilder.andWhere('goods.price >= :minPrice', { minPrice: dto.minPrice });
    } else if (dto.maxPrice !== undefined) {
      queryBuilder.andWhere('goods.price <= :maxPrice', { maxPrice: dto.maxPrice });
    }

    // 根据排序字段和方向排序
    if (dto.field && dto.order) {
      queryBuilder.orderBy(`goods.${dto.field}`, dto.order);
    }

    return standardPaginate(queryBuilder, { page: dto.page, pageSize: dto.pageSize });
  }

  async canExchangeGoods(goodsId: number, userPoints: number): Promise<{canExchange: boolean, message: string}> {
    const goods = await this.pointsGoodsRepository.findOneBy({
      id: goodsId,
    });

		const canExchange: boolean = userPoints >= goods.price;
		const message: string = canExchange ? '可以兑换' : '积分不足，无法兑换';

		return {
			canExchange,
			message,
		};
  }

  async exchangeGoods(userId: number, goods: PointsGoodsEntity): Promise<void> {
		await this.pointsGoodsRepository.update(goods.id, {
			exchangeCount: goods.exchangeCount + 1,
		});

    await this.pointsGoodsExchangeService.create(userId, goods.id, {
      title: `消耗${goods.price}积分`,
      imageUrl: goods.image,
    });
  }

  /**
   * 删除积分商品
   * @param id 商品ID
   * @param tenantId 租户ID
   * @returns 删除结果
   */
  async delete(id: number, tenantId: number): Promise<{ message: string }> {
    const existingGoods = await this.pointsGoodsRepository.findOne({
      where: { id, tenant: { id: tenantId } },
    });

    if (!existingGoods) {
      throw new BadRequestException('商品不存在或无权限访问');
    }

    // 检查商品是否已被兑换，如果已被兑换则不允许删除
    if (existingGoods.exchangeCount > 0) {
      throw new BadRequestException('该商品已有兑换记录，无法删除');
    }

    await this.pointsGoodsRepository.remove(existingGoods);

    return { message: '商品删除成功' };
  }
}
